package com.simplegui.swing;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;

import com.simplegui.api.Canvas;
import com.simplegui.api.ImageFile;
import com.simplegui.api.exceptions.NotImplementedException;

public class CanvasSwingImpl implements Canvas{

	private final BufferedImage image;

	public CanvasSwingImpl(BufferedImage panel) {
		this.image = panel;
	}

	@Override
	public void drawText(String text, Point point, Font font, Color color) {
		Graphics2D g = (Graphics2D) image.getGraphics();
		if (g != null){
			g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g.setColor(color);
			g.setFont(font);
			g.drawString(text, point.x, point.y);
		}
	}

	@Override
	public void drawLine(Point startPoint, Point endPoint, int lineWidth, Color color) {
		Graphics2D g = (Graphics2D) image.getGraphics();
		if (g != null){
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g.setColor(color);
			g.setStroke(new BasicStroke(lineWidth));
			g.draw(new Line2D.Float(startPoint.x, startPoint.y, endPoint.x, endPoint.y));
		}
	}

	@Override
	public void drawPolyLine(Point[] points, int lineWidth, Color color) {
		throw new NotImplementedException("com.simplegui.framework.CanvasImpl.drawPolyLine(Point[], int, Color)");
	}

	@Override
	public void drawPolygon(Point[] points, int lineWidth, Color lineColor) {
		drawPolygon(points, lineWidth, lineColor, null);
	}

	@Override
	public void drawPolygon(Point[] points, int lineWidth, Color lineColor, Color fillColor) {
		Graphics2D g = (Graphics2D) image.getGraphics();
		if (g != null){
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g.setStroke(new BasicStroke(lineWidth));
			int[] xpoints = new int[points.length];
			int[] ypoints = new int[points.length];
			for (int i = 0; i < points.length; i++) {
				xpoints[i] = points[i].x;
				ypoints[i] = points[i].y;
			}

			if (fillColor != null){
				g.setColor(fillColor);
				g.fill(new Polygon(xpoints, ypoints, points.length));
			}

			g.setColor(lineColor);
			g.draw(new Polygon(xpoints, ypoints, points.length));
		}
	}

	@Override
	public void drawCircle(Point center, int radius, int lineWidth, Color lineColor) {
		drawCircle(center, radius, lineWidth, lineColor, null);
	}

	@Override
	public void drawCircle(Point center, int radius, int lineWidth, Color lineColor, Color fillColor) {
		Graphics2D g = (Graphics2D) image.getGraphics();
		if (g != null){
			g.setStroke(new BasicStroke(lineWidth));
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			int width = radius*2;
			if (fillColor != null){
				g.setColor(fillColor);
				g.fillOval(center.x-radius, center.y-radius, width, width);
			}

			g.setColor(lineColor);
			g.drawOval(center.x-radius, center.y-radius, width, width);
		}
	}


	@Override
	public void drawImage(ImageFile image, Point centerSource, Dimension dimensionSource, Point centerDest, Dimension dimensionDest) {
		drawImage(image, centerSource, dimensionSource, centerDest, dimensionDest, 0d);
	}

	@Override
	public void drawImage(ImageFile image, Point centerSource, Dimension dimensionSource, Point centerDest, Dimension dimensionDest, double rotation) {
		Graphics2D g = (Graphics2D) this.image.getGraphics();
		if (g != null && image != null){
			int midDestWidth = dimensionDest.width / 2;
			int midDestHeight = dimensionDest.height / 2;
			int midSourceWidth = dimensionSource.width / 2;
			int midSourceHeight = dimensionSource.height / 2;

			AffineTransform at = new AffineTransform();
			at.setToRotation(rotation, centerDest.x, centerDest.y);
			g.setTransform(at);
			
			BufferedImage img = ((ImageFileSwingImpl)image).getImage();
			g.drawImage(img
					//  dx1 the x coordinate of the first corner of the destination rectangle.
					, centerDest.x - midDestWidth 
					//	dy1 the y coordinate of the first corner of the destination rectangle.
					, centerDest.y - midDestHeight
					//	dx2 the x coordinate of the second corner of the destination rectangle.
					, centerDest.x + midDestWidth
					//	dy2 the y coordinate of the second corner of the destination rectangle.
					, centerDest.y + midDestHeight

					//	sx1 the x coordinate of the first corner of the source rectangle.
					, Math.abs(centerSource.x - midSourceWidth)
					//	sy1 the y coordinate of the first corner of the source rectangle.
					, Math.abs(centerSource.y - midSourceHeight)
					//	sx2 the x coordinate of the second corner of the source rectangle.
					, Math.abs(centerSource.x + midSourceWidth)
					//	sy2 the y coordinate of the second corner of the source rectangle.
					, Math.abs(centerSource.y + midSourceHeight)
					, null);

		}
	}

	@Override
	public void setBackground(Color color) {
		drawPolygon(new Point[]{new Point(0,0), new Point(image.getWidth(), 0), new Point(image.getWidth(), image.getHeight()), new Point(0, image.getHeight())}, 1, color, color);
	}

	@Override
	public void clear() {
		Graphics2D g = (Graphics2D) image.getGraphics();
		if (g != null){
			g.clearRect(0, 0, image.getWidth(), image.getHeight());
		}

	}

}
